package com.xbongbong.parent.abstracts;

import com.xbongbong.formula.constant.Constant;
import com.xbongbong.i18n.util.I18nMessageUtil;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.paas.help.SerialNoHelp;
import com.xbongbong.paas.pojo.dto.FormDataAddGetDTO;
import com.xbongbong.paas.pojo.vo.FormDataAddGetVO;
import com.xbongbong.paas.redis.RedisPrefixConstant;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.paas.util.ExplainUtil;
import com.xbongbong.parent.interfaces.BusinessNewPageRenderService;
import com.xbongbong.parent.parse.data.LinkDataHelp;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.enums.lowcode.ButtonTypeEnum;
import com.xbongbong.pro.formexplain.pojo.dto.HandlerExplainDTO;
import com.xbongbong.pro.formexplain.pojo.vo.HandlerExplainVO;
import com.xbongbong.pro.lowcodeconfig.pojo.dto.LowCodeConfigGetDTO;
import com.xbongbong.pro.lowcodeconfig.pojo.vo.LowCodeConfigGetVO;
import com.xbongbong.pro.permission.pojo.dto.VerifyAddPermissionDTO;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.model.FormConfigModel;
import com.xbongbong.sys.help.ProPermissionHelp;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;

/**
 * @author 吴峰
 * @date 2022/01/18 19:28
 */
@Component
public abstract class AbstractNewPageRenderService<F> implements BusinessNewPageRenderService<F> {

    private static final Logger LOGGER = LoggerFactory.getLogger(AbstractNewPageRenderService.class);


    @Resource
    private SerialNoHelp serialNoHelp;
    @Resource
    private LinkDataHelp linkDataHelp;
    @Resource
    private FormConfigModel formConfigModel;

    @Override
    public FormDataAddGetVO addGet(FormDataAddGetDTO formDataAddGetDTO) throws XbbException {
        try {
            //新建表单权限校验
            validatePermission(formDataAddGetDTO);
            // 低代码配置
            String corpid = formDataAddGetDTO.getCorpid();
            Long formId = formDataAddGetDTO.getFormId();
            Integer businessType = formDataAddGetDTO.getBusinessType();
            LowCodeConfigGetDTO lowCodeConfigGetDTO = new LowCodeConfigGetDTO();
            lowCodeConfigGetDTO.setCorpid(corpid);
            lowCodeConfigGetDTO.setFormId(formId);
            lowCodeConfigGetDTO.setBusinessType(businessType);
            lowCodeConfigGetDTO.setLoginUser(formDataAddGetDTO.getLoginUser());
            lowCodeConfigGetDTO.setType(ButtonTypeEnum.ADD.getCode());
            LowCodeConfigGetVO lowCodeConfigGetVO = getLowCodeConfig(lowCodeConfigGetDTO);
            // 获取表单
            F paasFormEntityExt = getForm(formDataAddGetDTO);
            // 获取字段解释
            List<FieldAttrEntity> explainList = getExplain(formDataAddGetDTO);
            // 通用层字段解释处理
            HandlerExplainDTO handlerExplainDTO = new HandlerExplainDTO();
            BeanUtil.copyProperties(formDataAddGetDTO, handlerExplainDTO, false);
            handlerExplainDTO.setExplainList(explainList);
            HandlerExplainVO handlerExplainVO = handleExplain(handlerExplainDTO, paasFormEntityExt);

            explainList = handlerExplainVO.getHeadList();
            // 业务层字段解释处理
            businessHandleExplain(formDataAddGetDTO, explainList, paasFormEntityExt);
            // todo 此处逻辑是否可以放入com.xbongbong.parent.interfaces.BusinessNewPageRenderService.handleExplain
            List<String> unableEditMemo= Arrays.asList(I18nMessageUtil.getMessage(StringConstant.AUTO_GEN_FIELD, Locale.US), I18nMessageUtil.getMessage(StringConstant.AUTO_GEN_FIELD, Locale.CHINA));
            for ( FieldAttrEntity fieldAttrEntity : explainList ) {
                // fix:18442 【移动端、web端】新建、编辑页面，不展示系统自动生成字段
                if (unableEditMemo.contains(fieldAttrEntity.getUnableEditMemo())) {
                    fieldAttrEntity.setVisible(0);
                }
            }
            // 设置默认的关联数据
            linkDataHelp.setDefaultLinkData(explainList, formDataAddGetDTO, handlerExplainVO);
            Map<String, FieldAttrEntity> explainMap = ExplainUtil.getExplainMapByList(explainList, null);
            // 获取流水号
            String serialNo = getSerialNo(explainMap, corpid, formId);
            FormDataAddGetVO formDataAddGetVO = new FormDataAddGetVO();
            formDataAddGetVO.setLowCodeConfig(lowCodeConfigGetVO);
            formDataAddGetVO.setExplainList(explainList);
            formDataAddGetVO.setSerialNo(serialNo);
            // 返回数据封装
            formatSaasAttrToReturn(formDataAddGetDTO, formDataAddGetVO, paasFormEntityExt);
            String value = formConfigModel.getConfigValueByRedis(RedisPrefixConstant.ASSIGNMENT_RULES, corpid, formId, formDataAddGetDTO.getSaasMark(), formDataAddGetDTO.getBusinessType(), "0");
            if (StringUtil.isNotEmpty(value)) {
                formDataAddGetVO.setAssignmentRules(Integer.valueOf(value));
            }
            return formDataAddGetVO;
        } catch (XbbException e) {
            throw e;
        } catch (Exception e){
            LOGGER.error("com.xbongbong.parent.service.abstracts.AbstractNewPageRenderService.addGet error", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }

    }

    @Override
    public void validatePermission(FormDataAddGetDTO formDataAddGetDTO) throws XbbException {
        VerifyAddPermissionDTO verifyAddPermissionDTO = new VerifyAddPermissionDTO();
        BeanUtil.copyProperties(formDataAddGetDTO, verifyAddPermissionDTO);
        ProPermissionHelp.verifyAddPermission(verifyAddPermissionDTO);
    }

    @Override
    public String getSerialNo(Map<String, FieldAttrEntity> explainMap, String corpid, Long formId) throws XbbException {
        // 获取流水号
        String serialNo = "";
        FieldAttrEntity fieldAttrEntity = explainMap.get(FieldTypeEnum.SERIALNO.getAlias());
        if (explainMap.containsKey(FieldTypeEnum.SERIALNO.getAlias()) && fieldAttrEntity.getFieldType().equals(FieldTypeEnum.SERIALNO.getType()) && Objects.equals(fieldAttrEntity.getStrictController(), Constant.ZERO)) {
            serialNo = serialNoHelp.getSerialNo(serialNo, corpid, formId, fieldAttrEntity);
        }
        return serialNo;
    }
}
